package br.com.puertorico.model.querybuilder.formatters;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle;

/**
 * Para realizacao de busca fonetica
 *
 * @author Daniel
 * @version 1.0.0
 */
public class BuscaBRUtils {

    private static final ResourceBundle CHARS;

    private static final String AS;

    private static final String ES;

    private static final String IS;

    private static final String OS;

    private static final String US;

    private static final String CEDILHA;

    private static final List<ReplaceItem> REPLACE_LIST;
    static {
        CHARS = ResourceBundle.getBundle("br.ufms.nin.components.generic.jpa.querybuilder.formatters.chars");
        AS = CHARS.getString("vogal.a");
        ES = CHARS.getString("vogal.e");
        IS = CHARS.getString("vogal.i");
        OS = CHARS.getString("vogal.o");
        US = CHARS.getString("vogal.u");
        CEDILHA = CHARS.getString("consoante.cedilha");
        REPLACE_LIST = new ArrayList<ReplaceItem>();
        REPLACE_LIST.add(new ReplaceItem("BR", "B", 0));
        REPLACE_LIST.add(new ReplaceItem("CA", "K", 0));
        REPLACE_LIST.add(new ReplaceItem("CO", "K", 0));
        REPLACE_LIST.add(new ReplaceItem("CU", "K", 0));
        REPLACE_LIST.add(new ReplaceItem("CK", "K", 0));
        REPLACE_LIST.add(new ReplaceItem("Q", "K", 0));
        REPLACE_LIST.add(new ReplaceItem("LH", "L", 0));
        REPLACE_LIST.add(new ReplaceItem("NH", "N", 0));
        REPLACE_LIST.add(new ReplaceItem("CS", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("CI", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("CE", "S", 0));
        REPLACE_LIST.add(new ReplaceItem(CEDILHA, "S", 0));
        REPLACE_LIST.add(new ReplaceItem("CH", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("RS", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("TS", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("X", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("Z", "S", 0));
        REPLACE_LIST.add(new ReplaceItem("CT", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("RT", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("ST", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("TR", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("TL", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("ST", "T", 0));
        REPLACE_LIST.add(new ReplaceItem("GE", "J", 0));
        REPLACE_LIST.add(new ReplaceItem("RJ", "J", 0));
        REPLACE_LIST.add(new ReplaceItem("GM", "M", 0));
        REPLACE_LIST.add(new ReplaceItem("MD", "M", 0));
        REPLACE_LIST.add(new ReplaceItem("PH", "F", 0));
        REPLACE_LIST.add(new ReplaceItem("PR", "P", 0));
        REPLACE_LIST.add(new ReplaceItem("RM", "SM", 0));
        REPLACE_LIST.add(new ReplaceItem("W", "V", 0));
        REPLACE_LIST.add(new ReplaceItem("Y", "I", 0));
        REPLACE_LIST.add(new ReplaceItem("ND", "N", 0));
        REPLACE_LIST.add(new ReplaceItem("N", "M", 1));
        REPLACE_LIST.add(new ReplaceItem("BL", "B", 2));
        REPLACE_LIST.add(new ReplaceItem("GI", "J", 2));
        REPLACE_LIST.add(new ReplaceItem("MJ", "J", 3));
        REPLACE_LIST.add(new ReplaceItem("GR", "G", 3));
        REPLACE_LIST.add(new ReplaceItem("GL", "G", 3));
        REPLACE_LIST.add(new ReplaceItem("MG", "G", 3));
        REPLACE_LIST.add(new ReplaceItem("RG", "G", 3));
        Collections.sort(REPLACE_LIST);
    }

    /**
     * 1. Converter todas as letras para Maiusculo; <br />
     * 2. Eliminar todos os acentos; 3. Garante que nao possui espacoes em branco
     *
     * @param palavra
     * @return
     */
    public static String removeAcentos(String palavra) {
        palavra = palavra.toUpperCase();
        palavra = palavra.replaceAll(AS, "A").replaceAll(ES, "E").replaceAll(IS, "I")
                         .replaceAll(OS, "O").replaceAll(US, "U");
        return palavra;
    }

    private static String initTabelaSubstituicao(String palavra) {
        // substituir terminacao AO por M
        if (palavra.endsWith("AO")) {
            palavra = palavra.substring(0, palavra.lastIndexOf("AO")) + "M";
        }
        // fazer substituicoes
        for (ReplaceItem item : REPLACE_LIST) {
            if (palavra.indexOf(item.getFrom()) > -1) {
                palavra = palavra.replaceAll(item.getFrom(), item.getTo());
            }
        }
        // Eliminar as terminacoes S, Z, R, M, N, AO e L;
        if (palavra.matches(".*[SZRMNL]{1}$|.*[AO]{2}$")) {
            palavra = palavra.substring(0, palavra.length() - 1);
        }
        // transforma o L com som de U em U
        if (palavra.matches(".*[AEIOU]{1}L[BCDFGHJKMNPQRSTWXZ]{1}.*")) {
            for (int i = 0; i < palavra.length(); i++) {
                int j = i + 3;
                if (j > palavra.length() - 1) {
                    break;
                }
                String sub = palavra.substring(i, j);
                if (sub.matches("[AEIOU]{1}L[BCDFGHJKMNPQRSTWXZ]{1}")) {
                    String regexp = "[" + sub + "]{3}";
                    // ESCA-JAVA0119:
                    palavra = palavra.replaceAll(regexp, sub.replace('L', 'U'));
                }
            }
        }
        // agora substitui L po R
        palavra = palavra.replaceAll("L", "R");
        // Remove as vogais e o H
        palavra = palavra.replaceAll("[AEIOUH]", "");
        // remover letras duplicadas
        StringBuilder novaPalavra = new StringBuilder();
        for (int i = 0; i < palavra.length(); i++) {
            if (novaPalavra.toString().equals("")
                    || novaPalavra.toString().charAt(novaPalavra.length() - 1) != palavra.charAt(i)) {
                novaPalavra.append(palavra.charAt(i));
            }
        }
        return novaPalavra.toString();
    }

    /**
     * @param palavra
     * @return
     */
    public static String codigoBuscaBr(String palavra) {
        /*
         * if (palavra == null || palavra.trim().equals("") || palavra.length() <= 3) { return
         * palavra; }
         */
        palavra = removeAcentos(palavra);
        palavra = initTabelaSubstituicao(palavra);
        return palavra;
    }

}
